package com.xuecheng.framework.exception;

import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

/**
 * 统一异常捕获类
 */
@ControllerAdvice // 控制器增强
@RestController // 返回结果为json
public class ExceptionCatch {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);

    // 定义一个Map, 存放错误信息和错误类型
    //ImmutableMap, 谷歌工具, 创建后不能更改,线程安全
    private static ImmutableMap<Class<? extends Throwable>, ResultCode> EXCEPTIONS;
    //定义Map的builder对象,去构建一个ImmutableMap
    protected static ImmutableMap.Builder<Class<? extends Throwable>, ResultCode> builder = ImmutableMap.builder();

    static {
        // 构建异常Map信息
        builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_JSON_PARAMETER);
    }

    // 当捕获到这个异常的时候, 执行下面的方法
    @ExceptionHandler(CustomException.class)  // 捕获
    public ResponseResult customException(CustomException customException) {
        // 记录日志
        LOGGER.error("捕获到异常", customException);
        // 返回代码
        ResultCode resultCode = customException.getResultCode();
        return new ResponseResult(resultCode);
    }

    @ExceptionHandler(Exception.class)  // 可以捕获所有的异常 也可以 单独指定异常 详细化处理
    public ResponseResult exception(Exception exception) {
        // 记录日志
        LOGGER.error("捕获到非自定义的异常: {}", exception.getMessage());
        if (EXCEPTIONS == null) {
            EXCEPTIONS = builder.build();    //EXCEPTIONS构建成功
        }
        // 在异常Map对象中找对应异常, 找得到就按照对应代码响应,找不到就返回999
        ResultCode code = EXCEPTIONS.get(exception.getClass());
        if (code!=null){
            // 找到就返回对应的错误代码
            return new ResponseResult(code);
        }else {
            // 找不到就返回9999
            ResultCode resultCode = CommonCode.SERVER_ERROR;
            return new ResponseResult(resultCode);
        }
    }

}
